package com.example.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.admin.common.exception.BusinessException;
import com.example.admin.entity.SysRole;
import com.example.admin.entity.SysRoleMenu;
import com.example.admin.entity.SysUser;
import com.example.admin.entity.SysUserRole;
import com.example.admin.mapper.SysRoleMapper;
import com.example.admin.mapper.SysRoleMenuMapper;
import com.example.admin.mapper.SysUserMapper;
import com.example.admin.mapper.SysUserRoleMapper;
import com.example.admin.model.dto.RoleDTO;
import com.example.admin.model.dto.RoleRequest;
import com.example.admin.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private SysRoleMapper roleMapper;
    
    @Autowired
    private SysRoleMenuMapper roleMenuMapper;
    
    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Override
    public IPage<SysRole> getRolePage(RoleRequest request) {
        Page<SysRole> page = new Page<>(request.getCurrent(), request.getSize());
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        
        // 根据角色名称和编码模糊查询
        if (StringUtils.hasText(request.getName())) {
            wrapper.like(SysRole::getName, request.getName());
        }
        if (StringUtils.hasText(request.getCode())) {
            wrapper.like(SysRole::getCode, request.getCode());
        }
        
        wrapper.orderByDesc(SysRole::getCreateTime);
        
        return roleMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRole(RoleDTO roleDTO) {
        // 检查角色名称是否已存在
        Integer count = roleMapper.selectCount(
            new LambdaQueryWrapper<SysRole>()
                .eq(SysRole::getName, roleDTO.getName())
        );
        if (count > 0) {
            throw new BusinessException("角色名称已存在");
        }

        // 检查角色编码是否已存在
        count = roleMapper.selectCount(
            new LambdaQueryWrapper<SysRole>()
                .eq(SysRole::getCode, roleDTO.getCode())
        );
        if (count > 0) {
            throw new BusinessException("角色编码已存在");
        }

        // 创建角色
        SysRole role = new SysRole();
        role.setName(roleDTO.getName());
        role.setCode(roleDTO.getCode());
        role.setDescription(roleDTO.getDescription());
        role.setStatus(roleDTO.getStatus() != null ? roleDTO.getStatus() : 1);
        roleMapper.insert(role);

        // 分配菜单权限
        if (roleDTO.getMenuIds() != null && !roleDTO.getMenuIds().isEmpty()) {
            updateRoleMenus(role.getId(), roleDTO.getMenuIds());
        }
        
        log.info("创建角色成功: {}", role.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRole(RoleDTO roleDTO) {
        // 检查角色是否存在
        SysRole role = roleMapper.selectById(roleDTO.getId());
        if (role == null) {
            throw new BusinessException("角色不存在");
        }

        // 检查角色名称是否重复
        Integer count = roleMapper.selectCount(
            new LambdaQueryWrapper<SysRole>()
                .eq(SysRole::getName, roleDTO.getName())
                .ne(SysRole::getId, roleDTO.getId())
        );
        if (count > 0) {
            throw new BusinessException("角色名称已存在");
        }

        // 更新角色信息
        role.setName(roleDTO.getName());
        role.setDescription(roleDTO.getDescription());
        role.setStatus(roleDTO.getStatus());
        roleMapper.updateById(role);

        // 更新菜单权限
        if (roleDTO.getMenuIds() != null) {
            updateRoleMenus(role.getId(), roleDTO.getMenuIds());
        }
        
        log.info("更新角色成功: {}", role.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRole(Long id) {
        // 检查角色是否存在
        SysRole role = roleMapper.selectById(id);
        if (role == null) {
            throw new BusinessException("角色不存在");
        }
        
        // 检查是否有用户关联此角色
        Integer userCount = userRoleMapper.selectCountByRoleId(id);
        if (userCount > 0) {
            throw new BusinessException("该角色下存在关联用户，请先解除用户关联");
        }
        
        // 删除角色菜单关联
        roleMenuMapper.delete(
            new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, id)
        );
        
        // 删除角色
        roleMapper.deleteById(id);
        log.info("删除角色成功: {}", id);
    }

    @Override
    public RoleDTO getRoleById(Long id) {
        // 获取角色信息
        SysRole role = roleMapper.selectById(id);
        if (role == null) {
            throw new BusinessException("角色不存在");
        }
        
        // 转换为DTO
        RoleDTO roleDTO = new RoleDTO();
        BeanUtils.copyProperties(role, roleDTO);
        
        // 获取角色关联的菜单ID列表
        List<Long> menuIds = roleMenuMapper.selectMenuIdsByRoleId(id);
        roleDTO.setMenuIds(menuIds);
        
        return roleDTO;
    }

    @Override
    public IPage<SysUser> getRoleUsers(Long roleId, RoleRequest request) {
        Page<SysUser> page = new Page<>(request.getCurrent(), request.getSize());
        
        // 构建查询条件
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        
        // 根据用户名模糊查询
        if (StringUtils.hasText(request.getUsername())) {
            wrapper.like(SysUser::getUsername, request.getUsername());
        }
        
        // 查询指定角色下的用户
        List<Long> userIds = userRoleMapper.selectList(
            new LambdaQueryWrapper<SysUserRole>()
                .eq(SysUserRole::getRoleId, roleId)
        ).stream().map(SysUserRole::getUserId).collect(Collectors.toList());
        
        if (userIds.isEmpty()) {
            return new Page<>();
        }
        
        wrapper.in(SysUser::getId, userIds);
        wrapper.orderByDesc(SysUser::getCreateTime);
        
        return userMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleMenus(Long roleId, List<Long> menuIds) {
        // 检查角色是否存在
        if (roleMapper.selectById(roleId) == null) {
            throw new BusinessException("角色不存在");
        }
        
        // 删除原有的角色菜单关联
        roleMenuMapper.delete(
            new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, roleId)
        );
        
        // 保存新的角色菜单关联
        if (menuIds != null && !menuIds.isEmpty()) {
            List<SysRoleMenu> roleMenus = menuIds.stream()
                .map(menuId -> {
                    SysRoleMenu roleMenu = new SysRoleMenu();
                    roleMenu.setRoleId(roleId);
                    roleMenu.setMenuId(menuId);
                    return roleMenu;
                })
                .collect(Collectors.toList());
            
            for (SysRoleMenu roleMenu : roleMenus) {
                roleMenuMapper.insert(roleMenu);
            }
        }
        
        log.info("更新角色菜单成功, roleId: {}, menuIds: {}", roleId, menuIds);
    }

    @Override
    public IPage<SysUser> getAvailableUsers(RoleRequest request) {
        Page<SysUser> page = new Page<>(request.getCurrent(), request.getSize());
        
        // 构建查询条件
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        
        // 用户名模糊查询
        if (StringUtils.hasText(request.getUsername())) {
            wrapper.like(SysUser::getUsername, request.getUsername());
        }
        
        // 排除已关联的用户
        List<Long> existUserIds = userRoleMapper.selectList(
            new LambdaQueryWrapper<SysUserRole>()
                .eq(SysUserRole::getRoleId, request.getRoleId())
        ).stream().map(SysUserRole::getUserId).collect(Collectors.toList());
        
        if (!existUserIds.isEmpty()) {
            wrapper.notIn(SysUser::getId, existUserIds);
        }
        
        // 只查询正常状态的用户
        wrapper.eq(SysUser::getStatus, 1);
        wrapper.orderByDesc(SysUser::getCreateTime);
        
        return userMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUsers(Long roleId, List<Long> userIds) {
        // 检查角色是否存在
        if (roleMapper.selectById(roleId) == null) {
            throw new BusinessException("角色不存在");
        }
        
        // 检查用户是否已关联该角色
        List<Long> existUserIds = userRoleMapper.selectList(
            new LambdaQueryWrapper<SysUserRole>()
                .eq(SysUserRole::getRoleId, roleId)
                .in(SysUserRole::getUserId, userIds)
        ).stream().map(SysUserRole::getUserId).collect(Collectors.toList());
        
        // 过滤掉已关联的用户
        userIds = userIds.stream()
            .filter(userId -> !existUserIds.contains(userId))
            .collect(Collectors.toList());
        
        // 批量插入新的用户角色关联
        if (!userIds.isEmpty()) {
            List<SysUserRole> userRoles = userIds.stream()
                .map(userId -> {
                    SysUserRole userRole = new SysUserRole();
                    userRole.setUserId(userId);
                    userRole.setRoleId(roleId);
                    return userRole;
                })
                .collect(Collectors.toList());
            
            for (SysUserRole userRole : userRoles) {
                userRoleMapper.insert(userRole);
            }
            
            log.info("添加角色用户成功, roleId: {}, userIds: {}", roleId, userIds);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeUser(Long roleId, Long userId) {
        int count = userRoleMapper.delete(
            new LambdaQueryWrapper<SysUserRole>()
                .eq(SysUserRole::getRoleId, roleId)
                .eq(SysUserRole::getUserId, userId)
        );
        
        if (count > 0) {
            log.info("移除角色用户成功, roleId: {}, userId: {}", roleId, userId);
        }
    }
} 